package cn.yhp.mybatis.session;

import cn.yhp.mybatis.binding.MapperRegistry;
import cn.yhp.mybatis.datasource.druid.DruidDataSourceFactory;
import cn.yhp.mybatis.mapping.Environment;
import cn.yhp.mybatis.mapping.MappedStatement;
import cn.yhp.mybatis.transaction.jdbc.JdbcTransactionFactory;
import cn.yhp.mybatis.type.TypeAliasRegistry;

import java.util.HashMap;
import java.util.Map;

/**
 * 配置项，将配置信息封装传递,贯穿整个流程
 * @author yhp
 * @date 2023/11/18
 */
public class Configuration {

    /**
     * 环境【含数据源和事务工厂属性】
     */
    protected Environment environment;
    /**
     * mapper注册器
     */
    protected MapperRegistry mapperRegistry=new MapperRegistry(this);

    /**
     * 映射的语句，存入map集合
     */
    protected final Map<String, MappedStatement> mappedStatements=new HashMap<>();

    /**
     * 类型别名注册机
     */
    protected final TypeAliasRegistry typeAliasRegistry = new TypeAliasRegistry();

    public Configuration() {
        // 将事务工厂实现放入类型别名注册机
        typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class);
        typeAliasRegistry.registerAlias("DRUID", DruidDataSourceFactory.class);
    }

    /**
     * 存入Mapper的Class类型，作为key，并包装对应Mapper工厂对象一一对应
     * @param type
     * @param <T>
     */
    public <T> void addMapper(Class<T> type){
        mapperRegistry.addMapper(type);
    }

    /**
     * 获取指定Mapper的代理对象
     * @param type
     * @param sqlSession
     * @param <T>
     * @return
     */
    public <T> T getMapper (Class<T> type,SqlSession sqlSession){
        return mapperRegistry.getMapper(type,sqlSession);
    }

    /**
     * 将某个封装好的映射语句对象放入集合，并于后面执行sql获取
     * @param ms
     */
    public void addMappedStatement(MappedStatement ms){
        mappedStatements.put(ms.getId(),ms);
    }

    public MappedStatement getMappedStatement(String id){
        return mappedStatements.get(id);
    }

    public TypeAliasRegistry getTypeAliasRegistry() {
        return typeAliasRegistry;
    }

    public Environment getEnvironment() {
        return environment;
    }

    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }

}
